package me.stone.stanimeclient.core.ui.adapters

import android.graphics.Rect
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ItemDecoration
import me.stone.stanimeclient.core.common.extensions.dip
import me.stone.stanimeclient.core.data.mapper.toFanSimpleItem
import me.stone.stanimeclient.core.model.FanIntroItem
import me.stone.stanimeclient.core.ui.R
import me.stone.stanimeclient.core.ui.adapters.holder.DefaultViewHolder
import me.stone.stanimeclient.core.ui.adapters.listener.OnItemClickListener
import me.stone.stanimeclient.core.ui.adapters.refresh.PreInflaterHelper
import me.stone.stanimeclient.core.ui.databinding.ItemFanGridBinding
import me.stone.stanimeclient.core.ui.databinding.ItemFanListBinding
import me.stone.stanimeclient.core.ui.extensions.setPositionTag
import java.lang.ref.SoftReference
import kotlin.math.roundToInt

class FanIntroListGridAdapter
    : PagingDataAdapter<FanIntroItem, DefaultViewHolder>(DIFF_CALLBACK)
    , View.OnClickListener {

    companion object {

        private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<FanIntroItem>() {
            override fun areItemsTheSame(oldItem: FanIntroItem, newItem: FanIntroItem): Boolean {
                return oldItem.id == newItem.id
            }

            override fun areContentsTheSame(oldItem: FanIntroItem, newItem: FanIntroItem): Boolean {
                return oldItem == newItem
            }
        }

        const val GRID_SPAN_COUNT = 3

        private val preInflaterHelper = PreInflaterHelper.get()

    }

    enum class HolderViewType(val viewType: Int, val drawableId: Int) {
        LIST(R.layout.item_fan_list, R.drawable.ic_common_list) {
            override fun getViewDataBinding(parent: ViewGroup): ViewDataBinding {
                val view = preInflaterHelper.getView(parent, R.layout.item_fan_list)
                view.tag = "layout/item_fan_list_0"
                return DataBindingUtil.bind<ItemFanListBinding>(view)!!
            }

            override fun bindLayoutManager(recyclerView: RecyclerView) {
                recyclerView.layoutManager = LinearLayoutManager(recyclerView.context).apply {
                    orientation = LinearLayoutManager.VERTICAL
                }
            }
        },

        GRID(R.layout.item_fan_grid, R.drawable.ic_common_grid) {
            override fun getViewDataBinding(parent: ViewGroup): ViewDataBinding {
                val view = preInflaterHelper.getView(parent, R.layout.item_fan_grid, 6)
                view.tag = "layout/item_fan_grid_0"
                return DataBindingUtil.bind<ItemFanGridBinding>(view)!!
            }

            override fun bindLayoutManager(recyclerView: RecyclerView) {
                recyclerView.layoutManager = GridLayoutManager(
                    recyclerView.context, GRID_SPAN_COUNT
                )
            }
        };

        fun next() = when (this) {
            LIST -> GRID
            GRID -> LIST
        }

        abstract fun getViewDataBinding(parent: ViewGroup): ViewDataBinding

        abstract fun bindLayoutManager(recyclerView: RecyclerView)
    }

    private lateinit var mRecyclerView: SoftReference<RecyclerView>

    var onItemClickListener: OnItemClickListener<FanIntroItem>? = null

    var currentViewType = HolderViewType.LIST
        private set(value) {
            field = value
            mRecyclerView.get()?.let {
                field.bindLayoutManager(it)
            }
        }

    fun toggleStyle(): HolderViewType {
        currentViewType = currentViewType.next()
        return currentViewType
    }

    override fun getItemViewType(position: Int): Int {
        return when(currentViewType) {
            HolderViewType.LIST -> R.layout.item_fan_list
            HolderViewType.GRID -> R.layout.item_fan_grid
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DefaultViewHolder {
        val binding = currentViewType.getViewDataBinding(parent)
        return DefaultViewHolder(binding.root)
    }

    override fun onBindViewHolder(holder: DefaultViewHolder, position: Int) {
        val fanItem = getItem(position) ?: return
        val binding: ViewDataBinding? = when (currentViewType) {
            HolderViewType.LIST -> {
                DataBindingUtil.getBinding<ItemFanListBinding>(holder.itemView)?.apply {
                    item = fanItem
                }
            }
            HolderViewType.GRID -> {
                DataBindingUtil.getBinding<ItemFanGridBinding>(holder.itemView)?.apply {
                    item = fanItem.toFanSimpleItem()
                }
            }
        }
        holder.itemView.setPositionTag(position)
        holder.itemView.setOnClickListener(this)
        binding?.executePendingBindings()
    }

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        super.onAttachedToRecyclerView(recyclerView)
        mRecyclerView = SoftReference(recyclerView)
        recyclerView.setHasFixedSize(true)
        val dp4 = 4f.dip.roundToInt()
        if (recyclerView.paddingTop == 0 || recyclerView.paddingStart == 0) {
            recyclerView.setPaddingRelative(dp4, dp4, dp4, dp4)
        }
        if (recyclerView.itemDecorationCount == 0) {
            recyclerView.addItemDecoration(object : ItemDecoration() {
                override fun getItemOffsets(
                    outRect: Rect,
                    view: View,
                    parent: RecyclerView,
                    state: RecyclerView.State
                ) {
                    outRect.set(dp4, dp4, dp4, dp4)
                }
            })
        }
        currentViewType.bindLayoutManager(recyclerView)
    }

    override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
        mRecyclerView.clear()
    }

    override fun onClick(v: View) {
        (v.getTag(R.id.tag_key_position) as? Int)?.let { position ->
            getItem(position)?.let { item ->
                onItemClickListener?.onItemClicked(item)
            }
        }
    }

}